#if DEBUG_LEVEL > 0
#include <iostream>
using std::cout;
using std::endl;
#endif

#include "gui/GUIGameManager.h"
#include "Agent31.h"

GUIGameManager::GUIGameManager(Player** playerGroup) :
    GameManager(playerGroup),knockingPlayer(-1),waitingForHuman(false) {
  for (int i = 0; i < NUM_PLAYERS; i++) {
    players[i] = playerGroup[i];
    players[i]->setGame(&gameState);
  }
}

void GUIGameManager::run() {
  reportFirstDiscard();
  for (int i = 0; i < NUM_PLAYERS; i++) {
    players[i]->receiveDeal(gameState.deal(i));
  }
  isGameOver = false;
  waitingForHuman = false;
  winner = -1;

  playAgentTurns(0);
}

void GUIGameManager::playAgentTurns(int startPlayer) {
  Agent31* agent;
  int i = startPlayer;
  while (!isGameOver && (agent=dynamic_cast<Agent31*>(players[i]))) {
    if (i != knockingPlayer) {
      const Move& move = players[i]->decideMove();
      emit agentTurnOccurred(i);
      reportMove(move, i);
      updateState(i);
    }
    else {
      isGameOver = true;
    }
    i = (i+1)%NUM_PLAYERS;
  }
  if (i == knockingPlayer)
    isGameOver = true;
  checkWinner();
  if (!isGameOver)
    waitingForHuman = true;
}

void GUIGameManager::completeHumanTurn(int player, const Move& move) {
  reportMove(move, player);
  updateState(player);
  int nextPlayer = (player+1)%NUM_PLAYERS;
  checkWinner();
  if (!isGameOver)
    playAgentTurns(nextPlayer);
}

void GUIGameManager::reportFirstDiscard() {
  QString message("The ");
  message += gameState.getDiscardStack().GetCard(0).Name().c_str();
  message += " was dealt to the discard pile.\n";
  emit gameReport(message);
}

void GUIGameManager::updateState(int player) {
  if (players[player]->revealHand().Value()==31) {
    isGameOver = true;
    gameState.report31(player);
    winner = player;
  }
  else if (knockingPlayer < 0 && gameState.isLastRound()) {
    knockingPlayer = player;
  }
}

void GUIGameManager::reportMove(const Move& move, int player) {
  if (move.isValid()) {
    QString p,message;
    p = QString("Player %1").arg(player);
    message = p;
    if (move.knock) {
      message += " knocked.\n";
    }
    else {
      if (move.cardDrawn.GetIndex() < 53) {
        message += " drew a face-down card.\n";
      }
      else {
        message += " picked up the ";
        message += QString(move.cardPicked.Name().c_str()) + ".\n";
      }
      message += p;
      message += QString(" discarded the ");
      message += QString(move.cardDiscarded.Name().c_str()) + ".\n";
    }
    emit gameReport(message);
  }
}

void GUIGameManager::checkWinner() {
  if (isGameOver) {
    int maxScore = 0;
    if (winner < 0) {
      for (int i = 0; i < NUM_PLAYERS; i++) {
        int handValue = players[i]->revealHand().Value();
        if (handValue == maxScore) {
          if (knockingPlayer == -1)
            winner = -1;
          else if (i != knockingPlayer)
            winner = i;
        }
        else if (handValue > maxScore) {
          winner = i;
          maxScore = handValue;
        }
      }
    }
    else
      maxScore = 31;
    QString message;
    if (winner > -1)
      message = QString("Player %1 won with %2 points!").arg(winner).arg(maxScore);
    emit gameReport(message);
    emit gameOver();
  }
}